package com.seu.project.seuquiz.manager;

import com.seu.project.seuquiz.common.ErrorCode;
import com.seu.project.seuquiz.exception.BusinessException;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 专门提供 RedisLimiter 限流基础服务的（提供了通用的能力）
 */
@Service
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流操作
     * @param key 区分不同的限流器，比如不同的用户 id 应该分别统计
     */
    public void doRateLimit(String key) {
        // 创建一个名为key的限流器，每秒最多访问5次（用用户id作为key，每个用户都有不同的限流器）
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 设置限流器的统计规则
        /**
         * RateType.OVERALL 无论有多少台服务器都是放在一起统计的
         * 2: 频率
         * 1: 时间窗口
         * RateIntervalUnit.SECONDS: 时间单位
         */
        rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS);

        // 每当一个操作来后，请求一个令牌
        boolean canOp = rateLimiter.tryAcquire(1);
        // rateLimiter.tryAcquire(5);   // 每个请求占用几个令牌，如: 普通用户5个，会员1个

        // 没有令牌抛异常
        if (!canOp) {
            throw new BusinessException(ErrorCode.TOO_MANY_REQUEST);
        }
    }
}
